home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / ODMemMgr / Sources / MemMgrM.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  11.0 KB  |  434 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemMgrM.cpp
  3.  
  4.     Contains:    Mac-specific implementations of MemMgr calls
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.                  2/13/96    srf        Build variation for MacApp
  12.     
  13.         <10>    10/24/95    jpa        1293441: Added slush-fund. Allocate
  14.                                     temp-mem handles out of app heap if
  15.                                     absolutely necessary.
  16.          <9>     10/4/95    jpa        MMCopyHandle allocates in current heap's
  17.                                     area. [1289074]
  18.          <8>      5/5/95    TJ        jpa: ApplicZone --> ApplicationZone.
  19.          <7>      5/4/95    jpa        Added free-space fns, and maintain a
  20.                                     certain minimum free space in handle
  21.                                     allocation ops [1235657]
  22.          <6>     1/25/95    jpa        Removed HandToHand workaround now that
  23.                                     we're on Dagon a2. [1209733]
  24.          <5>     1/12/95    jpa        Took out five-dollar-sign mark and added
  25.                                     Radar bug 1209733. [1210981]
  26.          <4>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  27.          <3>    10/12/94    JA        Added 68k workaround for HandToHand; no
  28.                                     effect on PPC build.
  29.          <2>     9/29/94    RA        1189812: Mods for 68K build.
  30.          <1>     9/14/94    jpa        first checked in
  31.  
  32.     To Do:
  33.     In Progress:
  34.         
  35. */
  36.  
  37.  
  38. #ifndef _MEMMGR_
  39. #include "MemMgr.h"
  40. #endif
  41.  
  42. #ifndef _MEMMGRPV_
  43. #include "MemMgrPv.h"
  44. #endif
  45.  
  46. #ifndef _MEMDEBG_
  47. #include "MemDebg.h"
  48. #endif
  49.  
  50. #ifndef __MEMORY__
  51. #include <Memory.h>        // Mac memory manager
  52. #endif
  53.  
  54. #ifndef __ERRORS__
  55. #include <Errors.h>
  56. #endif
  57.  
  58.  
  59. const size_t kMaxHandleBlockSize = 0x7FFFFFFF;
  60.  
  61. #if MM_DEBUG
  62. const size_t kTempMemFudge = 1000*1024;
  63. #else
  64. const size_t kTempMemFudge =  100*1024;
  65. #endif
  66.  
  67.  
  68. static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig );
  69.  
  70.  
  71. static MMBoolean
  72. FreeSpaceLow( MMHandle h )
  73. {
  74.     if( !h )
  75.         return kMMFalse;
  76.     Zone *zone = ::HandleZone((Handle)h);
  77.     if( MemError() )
  78.         return kMMTrue;
  79.     size_t free,contig;
  80.     MMSystemFreeSpace(zone,&free,&contig);
  81.     return (free < kPlatformMinFreeSpace || contig < kPlatformMinContigSpace);
  82. }
  83.  
  84.  
  85. //========================================================================================
  86. // OPERATIONS ON RELOCATABLE BLOCKS (HANDLES)
  87. //========================================================================================
  88.  
  89.  
  90. //----------------------------------------------------------------------------------------
  91. // MMAllocateHandle
  92. //----------------------------------------------------------------------------------------
  93.  
  94. MMHandle MMAllocateHandle(size_t howBig)
  95. {
  96.     return MMAllocateHandleIn(howBig,gDefaultHeap->GetLocation());
  97. }
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // MMAllocateHandleIn
  101. //----------------------------------------------------------------------------------------
  102. #if defined(qMacApp)
  103. // What we really need is a hook to call thru. MMAllocateHandleIn should be overridable by the client.
  104. extern Handle MAAllocateHandle(size_t size);
  105. #endif
  106.  
  107. MMHandle MMAllocateHandleIn(size_t size, MMHeapLocation loc)
  108. {
  109. #if MMDebug
  110.     if( size>kMaxHandleBlockSize ) {
  111.         MM_WARN("Bogus size 0x%08lx for MMAllocateHandle",size);
  112.         return kMMNULL;
  113.     }
  114. #endif
  115.  
  116.     Handle handle;
  117.     OSErr err;
  118.     
  119.     switch( loc ) {
  120.         case kMMSysMemory:
  121.             handle = ::NewHandleSys(size);
  122.             err = MemError();
  123.             break;
  124.         case kMMAppMemory:
  125. #if !defined(qMacApp)
  126.             // No, let the application provided function decide
  127.             SetZone(ApplicationZone());
  128.             handle = ::NewHandle(size);
  129.             err = MemError();
  130. #else
  131.             // Call an external function to handle this
  132.             handle = MAAllocateHandle(size);
  133.             err = handle ? noErr : memFullErr;
  134. #endif
  135.             break;
  136.         case kMMTempMemory:
  137.             handle = ::TempNewHandle(size, &err);
  138.             break;
  139.         default:
  140.             MM_WARN("MMAllocateHandleIn: Bogus memory source!");
  141.             return 0;
  142.     }
  143.     
  144.     if( err!=noErr && err!=memFullErr )
  145.         MM_WARN("MMAllocateHandle got err %d",err);
  146.     
  147.     if( FreeSpaceLow(handle) ) {
  148.         DisposeHandle(handle);
  149.         handle = kMMNULL;
  150.     }
  151.  
  152.     if( handle == kMMNULL && loc==kMMTempMemory ) {
  153.         // Allow temp-mem handle to be allocated out of app heap if there's room.
  154.         // It's easy for temp-mem to become totally wedged (just launch an app whose
  155.         // "preferred size" is greater than the amount available), which would
  156.         // otherwise totally prevent allocation of handles.
  157.         handle = (Handle) MMAllocateHandleIn(size,kMMAppMemory);
  158.     }
  159.     
  160. #if MMDebug
  161.     if( gValidate>0 && handle )
  162.         Zap(*(Handle)handle, size, 0xBBBBBBBB);
  163. #endif
  164.  
  165.     return (MMHandle) handle;
  166. }
  167.  
  168. //----------------------------------------------------------------------------------------
  169. // MMFreeHandle
  170. //----------------------------------------------------------------------------------------
  171.  
  172. void MMFreeHandle(MMHandle handle)
  173. {
  174.     if( handle != kMMNULL ) {
  175. #if MMDebug
  176.         if( gValidate>0 ) {
  177.             if( !MMValidateHandle(handle) )
  178.                 return;
  179.             Zap(*(Handle)handle, GetHandleSize((Handle)handle), 0xDD);
  180.         }
  181.         
  182.         if( HGetState((Handle)handle) & 0x20 ) {
  183.             MM_WARN("MMFreeHandle: Tried to dispose rsrc %p",handle);
  184.             return;
  185.         }
  186. #endif
  187.         
  188.         DisposeHandle((Handle)handle);
  189.         
  190. #if MMDebug
  191.         OSErr err = MemError();
  192.         if( err!=noErr )
  193.             MM_WARN("MMFreeHandle: DisposeHandle returned err %d",err);
  194. #endif
  195.     }
  196. }
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // MMCopyHandle
  200. //----------------------------------------------------------------------------------------
  201.  
  202. MMHandle MMCopyHandle( MMHandle handle )
  203. {
  204.     if( handle == kMMNULL ) {
  205.         MM_WARN("MMCopyHandle(NULL)!");
  206.         return kMMNULL;
  207.     }
  208.  
  209. #if MMDebug
  210.     if( gValidate>0 )
  211.         if( !MMValidateHandle(handle) )
  212.             return kMMNULL;
  213.     if( (HGetState((Handle)handle)&0x20) && !(HGetState((Handle)handle)&0x80) )
  214.         MM_WARN("Copying purgeable handle %p",handle);
  215. #endif
  216.  
  217.     size_t size = GetHandleSize((Handle) handle);
  218.     if( MemError() ) {
  219.         MM_WARN("MMCopyHandle got err %d",MemError());
  220.         return kMMNULL;
  221.     }
  222.     
  223.     MMHandle copy = MMAllocateHandle(size);
  224.     if( copy ) {
  225.         PlatformCopyMemory(*(Handle)handle,*(Handle)copy,size);
  226.         if( FreeSpaceLow(copy) ) {
  227.             MMFreeHandle(copy);
  228.             copy = kMMNULL;
  229.         }
  230.     }
  231.     return copy;
  232. }
  233.  
  234. //----------------------------------------------------------------------------------------
  235. // MMGetHandleSize(MMHandle handle)
  236. //----------------------------------------------------------------------------------------
  237.  
  238. size_t MMGetHandleSize(MMHandle handle)
  239. {
  240.     size_t    blkSize;
  241.     
  242. #if MMDebug
  243.     if( gValidate>0 )
  244.         if( !MMValidateHandle(handle) )
  245.             return 0;
  246. #endif
  247.         
  248.     blkSize = GetHandleSize((Handle) handle);
  249.     if( MemError() ) {
  250.         MM_WARN("MMGetHandleSize got err %d",MemError());
  251.         blkSize = 0;
  252.     }
  253.     return blkSize;
  254. }
  255.  
  256. //----------------------------------------------------------------------------------------
  257. // MMSetHandleSize(MMHandle handle, size_t blkSize)
  258. //----------------------------------------------------------------------------------------
  259.  
  260. MMBoolean MMSetHandleSize(MMHandle handle, size_t blkSize)
  261. {
  262.     size_t oldSize = ::GetHandleSize((Handle)handle);
  263.     
  264.     if( blkSize == oldSize )
  265.         return kMMTrue;
  266.     
  267. #if MMDebug
  268.     if( blkSize>kMaxHandleBlockSize ) {
  269.         MM_WARN("Bogus blkSize %08lx for MMSetHandleSize",blkSize);
  270.         return kMMFalse;
  271.     }
  272.     if( gValidate>0 ) {
  273.         if( !MMValidateHandle(handle) )
  274.             return kMMFalse;
  275.         // If block will shrink, zap area that will be lost:
  276.         if( blkSize < oldSize )
  277.             memset(OFFSET(*(Handle)handle,blkSize), 0xDD, oldSize-blkSize);
  278.     }
  279. #endif
  280.     
  281.     SetHandleSize((Handle) handle, blkSize);
  282.     OSErr err = MemError();
  283.     if( err ) {
  284.         if( err!=memFullErr )
  285.             MM_WARN("MMSetHandleSize got err %d",err);
  286.         return kMMFalse;
  287.     }
  288.     
  289.     if( blkSize>oldSize && FreeSpaceLow(handle) ) {
  290.         ::SetHandleSize((Handle)handle,oldSize);        // Back out the change
  291.         return kMMFalse;
  292.     }
  293.  
  294. #if MMDebug
  295.     // If block grew, zap new space at end:
  296.     if( gValidate>0 )
  297.         if( blkSize > oldSize )
  298.             memset(OFFSET(*(Handle)handle,oldSize),0xBB,(size_t)(blkSize-oldSize));    // Fill new space with BB
  299. #endif
  300.  
  301.     return kMMTrue;
  302. }
  303.  
  304. //----------------------------------------------------------------------------------------
  305. // MMLockHandle(MMHandle handle)
  306. //----------------------------------------------------------------------------------------
  307.  
  308. void* MMLockHandle(MMHandle handle)
  309. {
  310. #if MMDebug
  311.     if( gValidate>0 )
  312.         if( !MMValidateHandle(handle) )
  313.             return kODNULL;
  314. #endif
  315.         
  316.     HLock((Handle) handle);
  317.     OSErr err = MemError();
  318.     if( err ) {
  319.         MM_WARN("MMLockHandle got err %d",err);
  320.         return kMMNULL;
  321.     }
  322.     
  323.     return *(Handle) handle;
  324. }
  325.  
  326. //----------------------------------------------------------------------------------------
  327. // MMUnlockPtr(void* ptr)
  328. //----------------------------------------------------------------------------------------
  329.  
  330. void MMUnlockPtr(void* ptr)
  331. {
  332.     if( ptr==kMMNULL ) {
  333.         MM_WARN("MMUnlockPtr(NULL)!");
  334.     } else {
  335.         MMHandle handle = (MMHandle) RecoverHandle((Ptr) ptr);
  336.         if( MemError() )
  337.             MM_WARN("MMUnlockPtr(%p) got err %d",ptr,MemError());
  338.         else if (handle != kMMNULL) {
  339. #if MMDebug
  340.             if( HGetState((Handle)handle) & 0x80) )
  341.                 MM_WARN("MMUnlockPtr(%p): Hdl %p already unlocked",ptr,h);
  342. #endif
  343.             HUnlock((Handle) handle);
  344.         }
  345.     }
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // MMUnlockHandle(MMHandle handle)
  350. //----------------------------------------------------------------------------------------
  351.  
  352. void MMUnlockHandle(MMHandle handle)
  353. {
  354. #if MMDebug
  355.     if( gValidate>0 )
  356.         if( !MMValidateHandle(handle) )
  357.             THROW(kMMErrMemoryProblem);
  358. #endif
  359.         
  360.     HUnlock((Handle) handle);
  361.     if( MemError() )
  362.         MM_WARN("MMUnlockHandle(%p) got err %d",handle,MemError());
  363. }
  364.  
  365.  
  366. //----------------------------------------------------------------------------------------
  367. // MMSystemFreeSpace
  368. //----------------------------------------------------------------------------------------
  369.  
  370. void MMSystemFreeSpace( MMHeapLocation loc, size_t *total, size_t *contig )
  371. {
  372.     size_t tempTotal, tempContig;
  373.     if( !total ) total = &tempTotal;
  374.     if( !contig) contig= &tempContig;
  375.     
  376.     Zone *zone = kMMNULL;
  377.     
  378.     switch( loc ) {
  379.         case kMMSysMemory:
  380.             zone = SystemZone();
  381.             break;
  382.             
  383.         case kMMAppMemory:
  384.             zone = ApplicationZone();
  385.             break;
  386.             
  387.         case kMMTempMemory: {
  388.             // Find the temp zone by allocating a handle in it and then getting its zone.
  389.             // Cannot cache this value because the Process Mgr zone's header can move!
  390.             OSErr err;
  391.             Handle handle = ::TempNewHandle(1, &err);
  392.             if( handle ) {
  393.                 zone = ::HandleZone(handle);
  394.                 ::DisposeHandle(handle);
  395.             }
  396.         }
  397.     }
  398.     MMSystemFreeSpace(zone,total,contig);
  399. }
  400.  
  401.  
  402. static void MMSystemFreeSpace( Zone *zone, size_t *total, size_t *contig )
  403. {
  404.     if( zone ) {
  405.         Zone *curZone = GetZone();
  406.         SetZone(zone);
  407.         
  408.         *total = FreeMem();
  409.         *contig = MaxBlock();
  410.         size_t purgeTotal, purgeContig; 
  411.         PurgeSpace((long*)&purgeTotal,(long*)&purgeContig);
  412.         if( purgeTotal > *total )
  413.             *total = purgeTotal;
  414.         if( purgeContig > *contig )
  415.             *contig = purgeContig;
  416.  
  417.         // Return an unnaturally low number for Temp Mem availability, to make it easier
  418.         // to debug and to reflect the fact that running out of temp mem is incredibly
  419.         // dangerous to the whole system.
  420.         if( kTempMemFudge > 0 && zone!=ApplicationZone() && zone!=SystemZone() ) {
  421.             // (It would be nice to have a better way to detect the temp mem zone.)
  422.             if( *total >= kTempMemFudge )
  423.                 *total -= kTempMemFudge;
  424.             else
  425.                 *total = 0;
  426.             if( *contig > *total )
  427.                 *contig = *total;
  428.         }
  429.         
  430.         SetZone(curZone);
  431.     } else
  432.         *total = *contig = 0;
  433. }
  434.